Skip to content

docs(protocol): drop phantom labels and unbacked promises from the backward-compatibility page (#14210, #14245) - #14385

Merged
baozhoutao merged 1 commit into
mainfrom
claude/issue-14210-backward-compat-page-promises
Sep 2, 2026
Merged

docs(protocol): drop phantom labels and unbacked promises from the backward-compatibility page (#14210, #14245)#14385
baozhoutao merged 1 commit into
mainfrom
claude/issue-14210-backward-compat-page-promises

Conversation

@claude

@claude claude Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Fixes #14210
Fixes #14245

Both cards land in the same file, content/docs/protocol/backward-compatibility.mdx — triage said "one implementer, one PR is fine; two cards, two criteria," so each card's criterion is checked off separately below.

#14210 — phantom labels + unbacked deprecation-survival guarantee

Ruling (comment 5503137278, verbatim):

  1. Labels. Step 1 points at protocol:breaking (the only live label of that class). Step 2 drops the label instruction: a compatibility report is an ordinary issue — ⛔ no new compatibility label (a label exists only when it has a named reader; none does), and ⛔ not protocol:breaking, which marks proposals, not reports.
  2. The "minimum 2 MINOR releases" guarantee is deleted, not sourced. No mechanism exists (ADR-0049's dispositions are enforce / experimental / remove, with no dwell time), and the maintainer's 2026-08-27 ruling on transitions is verbatim 「项目在创业阶段,用户也很少,短期不考虑渐进」 — a promised dwell time contradicts a standing ruling, so citing one is not an option. The page states what is true: deprecations are retired at the boundary the ADR-0087 registry records, with no minimum survival window.

Criterion 1 — labels:

  • Breaking Change Process step 1 → protocol:breaking (confirmed live via GET /repos/objectstack-ai/objectstack/labels?per_page=100; breaking-change and compatibility do not exist in the label set).
    • Before: Breaking changes are proposed as GitHub issues with the `breaking-change` label.
    • After: Breaking changes are proposed as GitHub issues with the `protocol:breaking` label.
  • Reporting Compatibility Issues step 2 → label instruction dropped entirely.
    • Before: File a GitHub issue with the `compatibility` label.
    • After: File a GitHub issue describing the unintended change.

Criterion 2 — no unbacked dwell-time guarantee:

  • Deleted the "minimum 2 MINOR releases" claim everywhere it appeared on the page (Phase 2 heading, the mermaid diagram, and the callout), not just the one named callout — all three encoded the same false guarantee.
    • Before (heading): ### Phase 2: Migration Period (minimum 2 MINOR releases)
      After: ### Phase 2: Migration Period
    • Before (diagram): A["v3.2.0 — feature deprecated..."] --> B["v3.3.0 — migration period continues"] --> C["v3.4.0 — migration continues (minimum 2 minor releases)"] --> D["v3.5.0 — feature removed..."]
      After: a 3-node generic flow (Deprecation notice → Migration period → Removal) with no fabricated version numbers and no minimum-duration claim; the Removal node now names the ADR-0087 registry boundary.
    • Before (callout): **Minimum guarantee:** Deprecated features survive for at least **2 MINOR releases** before they can be removed. ...
      After: **No minimum survival window.** ObjectStack does not guarantee a deprecated feature survives for a fixed number of releases — [ADR-0049]'s dispositions for a flagged property are enforce, experimental, or remove, and none of them carries a dwell time. A deprecated feature is retired at the boundary the ADR-0087 registry records for it; ...

#14245 — re-derive the GA end-condition sentence

Ruling (comment 5503069318, verbatim):

Lands in: content/docs/protocol/backward-compatibility.mdx (the "tracked separately and deliberately not stated here" sentence, ~:207, re-derive). Replace with the ruled one-liner exactly as the gate header in scripts/check-changeset-no-major.mjs records it — the window closes at GA, strict semver resumes — ⛔ no dates, no version numbers, nothing the ruling does not contain. Provenance chain stays as the card states (director batch B 2026-09-01 「同意」 → #14043 / PR #14227 → this). Not releases/**, so no docs-only fence.

Criterion — GA end condition re-derived from the gate header, verbatim in substance:

  • Source read: scripts/check-changeset-no-major.mjs header, "END CONDITION" section — "**End condition: at GA — the fixed group's first general-availability major — the group returns to STRICT SEMVER.**" No dates, no version numbers in the source; none introduced here.
    • Before: the condition that closes the window is tracked separately and is deliberately not stated here.
    • After: the window closes at GA, and strict SemVer resumes from that point.

Full diff

--- a/content/docs/protocol/backward-compatibility.mdx
+++ b/content/docs/protocol/backward-compatibility.mdx
@@ -55,7 +55,7 @@ When a feature, schema property, or API is deprecated, ObjectStack follows a str
 - Runtime warning is emitted on first use (once per session)
 - Migration path is documented in the CHANGELOG
 
-### Phase 2: Migration Period (minimum 2 MINOR releases)
+### Phase 2: Migration Period
 
 - Deprecated feature continues to function without behavior changes
 - Documentation is updated with migration guides
@@ -75,13 +75,12 @@ Shipped examples: `17.2.0` retired `http_request_errors_total` and `sys_position
 
 FENCE mermaid
 flowchart TD
-    A["v3.2.0 — feature deprecated (warning emitted)"] --> B["v3.3.0 — migration period continues"]
-    B --> C["v3.4.0 — migration continues (minimum 2 minor releases)"]
-    C --> D["v3.5.0 — feature removed (earliest possible removal, MINOR)"]
+    A["Deprecation notice — feature marked deprecated (warning emitted)"] --> B["Migration period — deprecated feature keeps working, no behavior change"]
+    B --> C["Removal — retired at the boundary the ADR-0087 registry records (MINOR release, during the launch window)"]
 FENCE
 
 CALLOUT type="warn"
-**Minimum guarantee:** Deprecated features survive for at least **2 MINOR releases** before they can be removed. During the launch window the removal itself lands in a MINOR release, so a MINOR bump is where you should expect a removal to arrive.
+**No minimum survival window.** ObjectStack does not guarantee a deprecated feature survives for a fixed number of releases — [ADR-0049](https://github.com/objectstack-ai/objectstack/blob/main/docs/adr/0049-no-unenforced-security-properties.md)'s dispositions for a flagged property are enforce, `experimental`, or remove, and none of them carries a dwell time. A deprecated feature is retired at the boundary the ADR-0087 registry records for it; during the launch window that removal itself lands in a MINOR release, so a MINOR bump is where you should expect a removal to arrive.
 CALLOUT
 
 ---
@@ -109,7 +108,7 @@ Read the **Breaking?** column, not the version number: during the launch window
 
 ### Breaking Change Process
 
-1. **RFC (Request for Comments)** — Breaking changes are proposed as GitHub issues with the `breaking-change` label.
+1. **RFC (Request for Comments)** — Breaking changes are proposed as GitHub issues with the `protocol:breaking` label.
 2. **Deprecation** — The old behavior is deprecated in a MINOR release (see timeline above).
 3. **Migration Guide** — A detailed migration guide is published before the removal lands, in the release notes for the version that carries it.
 4. **Release** — During the launch window the breaking change ships in the next **MINOR** version, carrying a changeset entry marked `**BREAKING**`. `scripts/check-changeset-no-major.mjs` fails any pull request that declares a `major` bump, because under lockstep one `major` would promote all 69 published packages.
@@ -204,7 +203,7 @@ MAJOR releases do still happen — 17.0.0 was cut precisely because its breaking
 
 ### When it stops applying
 
-The tables and deprecation timeline above now state this rule directly, so the page no longer contradicts itself. Classic SemVer — where a breaking change once again requires a MAJOR — is the settled form the project returns to once the launch window closes; the condition that closes the window is tracked separately and is deliberately not stated here. Until it closes, **this section is the operative rule wherever any part of this page disagrees.**
+The tables and deprecation timeline above now state this rule directly, so the page no longer contradicts itself. Classic SemVer — where a breaking change once again requires a MAJOR — is the settled form the project returns to once the launch window closes: the window closes at GA, and strict SemVer resumes from that point. Until it closes, **this section is the operative rule wherever any part of this page disagrees.**
 
 ---
 
@@ -213,6 +212,6 @@ The tables and deprecation timeline above now state this rule directly, so the page
 If you encounter an unintended breaking change:
 
 1. **Check the CHANGELOG** — Verify the change was not documented as intentional.
-2. **Open an issue** — File a GitHub issue with the `compatibility` label.
+2. **Open an issue** — File a GitHub issue describing the unintended change.
 3. **Include a reproduction** — Provide a minimal code sample showing the breakage.
 4. **Reference the version** — Specify the exact versions where behavior changed.

(FENCE/CALLOUT above stand in for the literal MDX code-fence and Callout-component syntax — GitHub's body sanitizer strips angle-bracket-shaped text, so the diff is spelled with placeholders here; the real file uses the actual MDX syntax.)

Gates

Docs-only change (no package publishes anything) — skip-changeset label applied on open per this repo's convention: precedent PR #14211 (same page, same author, docs-only) carries documentation, size/s, skip-changeset.

node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack derived 29 local gate families for this path (content/docs/protocol/backward-compatibility.mdx). Reconciliation via --ran:

Run reconciliation — 29 derived, 28 run, 1 NOT-MEASURED, 0 UNRUN.
✓ dispatch-gates --ran: 29 derived famil(ies) accounted for — 28 run, 1 NOT-MEASURED.

The 1 NOT-MEASURED is node scripts/check-test-completeness.mjs, which grades a saved turbo run test CI log and cannot run standalone locally (own PREREQUISITE NOT MET message) — CI-only by design, not a finding.

All 28 runnable families passed at head 5ee7d7d93, including (after building the dependency closure — @objectstack/spec, @objectstack/formula, @objectstack/lint, @objectstack/client, @objectstack/client-react — that several pnpm --filter @objectstack/{spec,lint} doc gates import compiled output from):

  • pnpm --filter @objectstack/spec run check:docs229 generated files in sync
  • pnpm --filter @objectstack/spec run check:skill-examples259 prose examples type-check across 3 surface(s)
  • pnpm --filter @objectstack/lint run check:doc-formula-expressions / check:doc-security-posture — clean
  • pnpm check:doc-anchors, check:docs-single-h1, check:docs-redirects, check:doc-authoring, check:role-word, check:published-readme-links, check:vendor-version-stamps, check:react-page-adapter-contract, check:corpus-claim-drift, check:cross-package-test-inputs, check:docs-audit-scope, check:skill-identifier-liveness — all clean
  • node scripts/check-doc-frontmatter.mjs, check-doc-route-spelling.mjs, check-docs-section-name.mjs, check-section-landing-index.mjs, check-ci-filter-parity.mjs, check-cross-package-test-inputs.mjs, check-shard-attestation.mjs — all clean
  • node scripts/check-nul-bytes.mjs — clean (repo-wide scan, no raw control bytes)

check:pm-dispatch-gates (its own vitest pin suite) was not part of this card's derived list — this PR does not touch any gate/tool script, only the target MDX content, so no derivation family or its self-tests apply beyond the 29 above.

CI status on this draft is in_progress at time of report — the farm runs the remaining 171 unrelated families regardless; per the dispatch contract this report is delivered at draft-PR time, not after CI convergence.

Generated by Claude Code


Generated by Claude Code

…ckward-compatibility page

- Breaking Change Process step 1: point at the label that actually exists,
  `protocol:breaking`, instead of the never-created `breaking-change`.
- Reporting Compatibility Issues step 2: drop the `compatibility` label
  instruction entirely — no reader exists for it, so it does not exist either.
- Delete the unsourced "minimum 2 MINOR releases" deprecation-survival
  guarantee (heading, mermaid diagram, and callout) and state the true
  process instead: a deprecated feature is retired at the boundary the
  ADR-0087 registry records for it, with no minimum dwell time.
- Re-derive the "tracked separately and deliberately not stated here"
  sentence: the launch window closes at GA and strict SemVer resumes from
  that point, per `scripts/check-changeset-no-major.mjs`'s own end-condition
  header.

_Generated by [Claude Code](https://claude.ai/code/session_01WLJQhde67SeTccsmnBVarV)_
@claude claude Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 2, 2026
@github-actions github-actions Bot added size/s documentation Improvements or additions to documentation labels Sep 2, 2026
@baozhoutao
baozhoutao marked this pull request as ready for review September 2, 2026 04:10
@baozhoutao
baozhoutao enabled auto-merge September 2, 2026 04:11
@baozhoutao
baozhoutao added this pull request to the merge queue Sep 2, 2026
Merged via the queue into main with commit 4485f7d Sep 2, 2026
37 checks passed
@baozhoutao
baozhoutao deleted the claude/issue-14210-backward-compat-page-promises branch September 2, 2026 04:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/s skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants